package org.je.xml.stream;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 这个类主要用于匹配类型
 * 
 * @author fan yi feng
 */
public class TypeUtil
{
	private static List<Class<?>>	baseArray	= new ArrayList<Class<?>>();	// 存放基本类型的列表

	static {
		baseArray.add(boolean.class);// 1
		baseArray.add(byte.class);
		baseArray.add(char.class);
		baseArray.add(short.class);
		baseArray.add(int.class);
		baseArray.add(long.class);
		baseArray.add(float.class);
		baseArray.add(double.class);// 8

		baseArray.add(Boolean.class);// 1
		baseArray.add(Byte.class);
		baseArray.add(Character.class);
		baseArray.add(Short.class);
		baseArray.add(Integer.class);
		baseArray.add(Long.class);
		baseArray.add(Float.class);
		baseArray.add(Double.class);// 8

		baseArray.add(String.class);
		baseArray.add(Date.class);
	}

	/**
	 * 如果这个类无法被实例化 ， 则返回true
	 * 
	 * @param cl
	 */
	public static boolean isAbstract(Class<?> cl) {// ok
		return Modifier.isAbstract(cl.getModifiers());
	}

	/**
	 * @param cl
	 * @return
	 */
	public static boolean isBase(Class<?> cl) {// ok
		if (cl == null)
			throw new NullPointerException("cl-is-null");
		if (cl.isEnum()) // 后来增加的，枚举也算基本类型
			return true;
		return baseArray.contains(cl);
	}

	/**
	 * @param cl
	 * @return
	 */
	public static boolean isStructure(Class<?> cl) {
		if (cl == null)
			throw new NullPointerException("cl-is-null");
		return Collection.class.isAssignableFrom(cl) || Map.class.isAssignableFrom(cl);

	}

	/**
	 * @param cl
	 * @return
	 */
	public static boolean isCollection(Class<?> cl) { // ok
		if (cl == null)
			throw new NullPointerException("cl-is-null");
		return Collection.class.isAssignableFrom(cl);
	}

	/**
	 * @param cl
	 * @return
	 */
	public static boolean isList(Class<?> cl) {// ok
		if (cl == null)
			throw new NullPointerException("cl-is-null");
		return List.class.isAssignableFrom(cl);
	}

	/**
	 * @param cl
	 * @return
	 */
	public static boolean isSet(Class<?> cl) {// ok
		if (cl == null)
			throw new NullPointerException("cl-is-null");
		return Set.class.isAssignableFrom(cl);
	}

	/**
	 * @param cl
	 * @return
	 */
	public static boolean isMap(Class<?> cl) {
		if (cl == null)
			throw new NullPointerException("cl-is-null");
		return Map.class.isAssignableFrom(cl);
	}

	/**
	 * @param cl
	 * @return
	 */
	public static boolean isArray(Class<?> cl) {
		if (cl == null)
			throw new NullPointerException("cl-is-null");
		return cl.isArray();
	}

	/**
	 * @param cl
	 * @return
	 */
	public static int baseIndex(Class<?> cl) {
		for (int i = 0; i < baseArray.size(); ++i) {
			if (baseArray.get(i) == cl)
				return i;
		}
		return -1;
	}

	/**
	 * @param idx
	 * @return
	 */
	public static Class<?> getClassInBase(int idx) {
		return baseArray.get(idx);
	}

	/***
	 * @param cl
	 * @param useSuper
	 * @return array[field]
	 */
	public static List<Field> getFields(Class<?> cl, boolean useSuper) {
		if (cl == null) {
			throw new NullPointerException("cl-is-null");
		}
		List<Field> arr = new ArrayList<Field>();
		saveFields(cl, arr, useSuper);
		return arr;
	}

	private static void saveFields(Class<?> cl, List<Field> arr2save, boolean useSuper) {
		if (cl == null || cl == Object.class)
			return;
		for (Field f : cl.getDeclaredFields()) {
			f.setAccessible(true);
			arr2save.add(f);
		}
		if (!useSuper)
			return;
		saveFields(cl.getSuperclass(), arr2save, true);
	}
}
